#!/usr/bin/python
# -*- coding: UTF-8 -*-

'''
 * author: liuxh 2017.8.11
'''
import socket
import uuid
import time
from util import SignUtil
from hashlib import sha1
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
import os,logging
#定义一个列表
data = [1,3,2,5,7,6]
#定义一个元组作为字典索引
seq = ('productKey', 'deviceName', 'clientId', 'timestamp')

'''开启TLS时的认证文件目录'''
trust = 'F:/workspace/aliiot_python/root.cer' #修改为自己文件实际路径即可

'''日志格式配置'''
logging.basicConfig(level=logging.DEBUG,
                format='[%(filename)s]-(line:%(lineno)d)-[%(funcName)s]-%(message)s----%(asctime)s',
                datefmt='%y-%b %d %a %H:%M:%S')

"""初始化参数设定"""
deviceName = "liuxh"
productKey = "3y7iXH9wQDt"
secret = "RfwUrTm1zXsvxzdhlmhXvaBXOBUJdnPe"


#用于测试的topic
subTopic = "/" + productKey + "/" + deviceName + "/get"
pubTopic = "/" + productKey + "/" + deviceName + "/update"
message = '你好阿里云'.decode('utf-8')

class SimpleClient4IOT :

    def __init__(self, clientid=None):
        #这里是客户端需要的参数*******/
        self.clientId = self.get_localhost_ip()
        #MQTT服务器地址，TLS连接使用ssl开头
        self.targetServer = "ssl://" + productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com:1883"
        self.targetServer1 =  productKey + ".iot-as-mqtt.cn-shanghai.aliyuncs.com"
        self.targetServer2 =  "3y7iXH9wQDt.iot-as-mqtt.cn-shanghai.aliyuncs.com"
        
        
        dit = dict.fromkeys(seq)
        dit['productKey'] = productKey #这个是对应用户在控制台注册的 设备productkey
        dit['deviceName'] = deviceName #这个是对应用户在控制台注册的 设备name
        dit['clientId'] = self.clientId
        t = int(round(time.time()*1000)) #获取系统当前时间
        dit['timestamp'] = str(t)
        
        #客户端ID格式，两个||之间的内容为设备端自定义的标记，字符范围[0-9][a-z][A-Z]
        self.params = dit
        self.mqttclientId = self.clientId + "|securemode=2,signmethod=hmacsha1,timestamp=" + str(t) + "|"
        self.mqttUsername = deviceName + "&" + productKey #mqtt用户名格式
        self.mqttPassword = SignUtil.SignUtil().sign(sha1, secret, **self.params)#签名,固定使用hamc加密
        self.connec()
#         self.client.subscribe(self.subTopic)
#         self.client.loop_forever()
#         while True:
#             self.client.loop()

        
    def connec(self):
        logging.info("进行连接-服务器地址: " + self.targetServer1);  
        self.client = mqtt.Client(client_id=self.mqttclientId, clean_session=False, userdata=None, protocol=mqtt.MQTTv31)
        self.client.on_publish = self.on_publish
        self.client.on_connect = self.on_connect 
        self.client.on_disconnect = self.on_disconnect 
        self.client.on_message = self.on_message
        self.client.on_subscribe = self.on_subscribe  
        self.client.tls_insecure_set(True) #检查hostname的cert认证
        self.client.tls_set(trust) #设置认证文件
        self.setAutho() #设置用户名和密码
        self.client.connect( self.targetServer1 ,port=1883, keepalive=65) #向服务器发起连接
        time.sleep(1)#这里要加延时，否则订阅不成功，原因未知
        self.client.subscribe(subTopic)#str: /3y7iXH9wQDt/liuxh/get
        time.sleep(1)#这里要加延时，否则发送不成功，原因未知
        self.client.publish(pubTopic,message)#str: /3y7iXH9wQDt/liuxh/get
        self.client.loop_forever()
    
    def setAutho(self):
        self.client.username_pw_set(self.mqttUsername, self.mqttPassword)   
        
        
    #获得主机IP地址
    def get_localhost_ip(self):
        self.local_ip = socket.gethostbyname(socket.gethostname())
        return self.local_ip
    
    #获得主机MAC地址
    def get_localhost_mac(self): 
        mac=uuid.UUID(int = uuid.getnode()).hex[-12:] 
        return ":".join([mac[e:e+2] for e in range(0,11,2)])   

  
    
    
    #创建客户端标识
    def SetClientId(self):
        return self.get_localhost_ip()
    
    
    '''  
    /*
     *clean_session = 0 状态下，调用该函数可以放弃 会话 
     * 清理会话标志 0 的客户端连接时， 它请求服务端在连接断开后保留它的 MQTT 会话状态。 如果打
     *算在之后的某个时间点重连到这个服务端， 客户端连接应该只使用清理会话标志 0。当客户端决定
     *之后不再使用这个会话时，应该将清理会话标志设置为 0 最后再连接一次，然后断开连接
     *
     */
    '''
    def destroy_session(self):
        self.client = mqtt.Client(client_id=self.mqttclientId, clean_session=False, userdata=None, protocol=mqtt.MQTTv31)
        self.client.connect( self.targetServer1 ,port=1883, keepalive=65) #向服务器发起连接
        self.client.disconnect()
        
        
        
        
        
        
        
        
    '''回调函数'''
    def on_connect(self, mqttc, obj, flags, rc):
#         print("Connection returned " + str(rc))
        if str(rc)=='0':
            logging.info("连接已被服务端接受")
        elif str(rc)=='1':
            logging.info("连接已拒绝，不支持的协议版本")
        elif str(rc)=='2':
            logging.info("连接已拒绝， 不合格的客户端标识符")
        elif str(rc)=='3':
            logging.info("连接已拒绝， 服务端不可用")
        elif str(rc)=='4':
            logging.info("连接已拒绝，无效的用户名或密码")

    def on_message(self, mqttc, obj, msg):
        print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
#         self.client.disconnect()
    
    def on_publish(self, mqttc, obj, mid):
        print("mid: "+str(mid))
    
    def on_subscribe(self, mqttc, obj, mid, granted_qos):
        print("Subscribed: "+str(mid)+" "+str(granted_qos))
    
    def on_log(self, mqttc, obj, level, string):
        print(string)
        
    def on_disconnect(self, client, userdata, rc):
        pass
#         if rc != 0:
#             print("连接断开，准备重新发起连接.")
#             self.client.reconnect()
    
    
s = SimpleClient4IOT()
# print s.get_localhost_mac() 
#     
# print s.SetDictParments()
# print s.xu_sort(data)
    